package com.sxr.webflux.impl;

import com.sxr.file.FileResponse;
import com.sxr.integration.SecureFileRequest;
import com.sxr.integration.SecureFileService;
import com.sxr.webflux.ReactiveFileService;
import com.sxr.webflux.util.ReactiveRequestParser;
import com.sxr.webflux.util.ReactiveResponseWriter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.HashMap;
import java.util.Map;

/**
 * 默认响应式文件服务实现
 * 将WebFlux API适配到核心业务逻辑
 *
 * @author SXR
 * @since 1.0.0
 */
public class DefaultReactiveFileService implements ReactiveFileService {

    private final SecureFileService secureFileService;
    private final ReactiveRequestParser requestParser;
    private final ReactiveResponseWriter responseWriter;

    public DefaultReactiveFileService(SecureFileService secureFileService) {
        this.secureFileService = secureFileService;
        this.requestParser = new ReactiveRequestParser();
        this.responseWriter = new ReactiveResponseWriter();
    }

    @Override
    public Mono<Void> handleSecureDownload(ServerHttpRequest request, ServerHttpResponse response) {
        return requestParser.parseSecureFileRequest(request, false)
                .flatMap(fileRequest -> processFileRequest(fileRequest, false))
                .flatMap(fileResponse -> responseWriter.writeFileResponse(fileResponse, response))
                .onErrorResume(throwable -> handleError(response, 500, "Internal server error: " + throwable.getMessage()));
    }

    @Override
    public Mono<Void> handleSecurePreview(ServerHttpRequest request, ServerHttpResponse response) {
        return requestParser.parseSecureFileRequest(request, true)
                .flatMap(fileRequest -> processFileRequest(fileRequest, true))
                .flatMap(fileResponse -> responseWriter.writeFileResponse(fileResponse, response))
                .onErrorResume(throwable -> handleError(response, 500, "Internal server error: " + throwable.getMessage()));
    }



    @Override
    public Mono<Void> healthCheck(ServerHttpRequest request, ServerHttpResponse response) {
        Map<String, String> status = new HashMap<>();
        status.put("status", "UP");
        status.put("service", "SXR File Signature WebFlux Adapter");
        status.put("version", "1.0.0");
        status.put("adapter", "webflux");

        return responseWriter.writeJsonResponse(status, response);
    }

    /**
     * 处理文件请求
     */
    private Mono<FileResponse> processFileRequest(SecureFileRequest fileRequest, boolean isPreview) {
        return Mono.fromCallable(() -> {
            if (isPreview) {
                return secureFileService.handleSecurePreview(fileRequest);
            } else {
                return secureFileService.handleSecureDownload(fileRequest);
            }
        }).subscribeOn(Schedulers.boundedElastic()); // 使用有界弹性调度器处理阻塞IO
    }



    /**
     * 处理错误响应
     */
    private Mono<Void> handleError(ServerHttpResponse response, int statusCode, String message) {
        return responseWriter.writeErrorResponse(statusCode, message, response);
    }

    /**
     * 构建JSON响应
     */
    private String buildJsonResponse(boolean success, String url, String error) {
        StringBuilder json = new StringBuilder();
        json.append("{");
        json.append("\"success\":").append(success);

        if (success && url != null) {
            json.append(",\"url\":\"").append(escapeJson(url)).append("\"");
        }

        if (!success && error != null) {
            json.append(",\"error\":\"").append(escapeJson(error)).append("\"");
        }

        json.append("}");
        return json.toString();
    }

    /**
     * JSON字符串转义
     */
    private String escapeJson(String str) {
        if (str == null) {
            return "";
        }
        return str.replace("\"", "\\\"")
                  .replace("\\", "\\\\")
                  .replace("\n", "\\n")
                  .replace("\r", "\\r")
                  .replace("\t", "\\t");
    }
}
